# coding=utf-8
"""
Copyright (c) Huawei Technologies Co., Ltd. 2020-2028. All rights reserved.
Description:
FileName：intelligence_ctl.py
Author: h00568282/huangbin 
Create Date: 2025/9/9 22:04
Notes:

"""
# svcctl.py
import json
import logging.config
import socket
from typing import Dict, Any

import rich_click as click
from rich.console import Console
from rich.prompt import Confirm
from rich.traceback import Traceback

from sys_intd.constant import SOCKET_PATH, LOG_FILE_CONFIG
from sys_intd.manager import McpServerManager
import subprocess
from sys_intd import __version__

logging.config.fileConfig(LOG_FILE_CONFIG)
logger = logging.getLogger('sampleLogger')
logging.basicConfig(level=logging.DEBUG)  # 在程序最开头加

console = Console()
CONTEXT_SETTINGS: Dict[str, Any] = dict(help_option_names=[])


def process_intelligenced_msg(response):
    response = json.loads(response)
    status = response.get("status")
    message = response.get("message")

    console.print(f"status: {status}.")
    for line in message:
        console.print(line)


def send_command(msg: Dict[str, Any]):
    try:
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.connect(SOCKET_PATH)
        sock.sendall(json.dumps(msg).encode('utf-8'))
        response = sock.recv(4096).decode('utf-8')
        # logger.info(json.dumps(json.loads(response), indent=2))
        process_intelligenced_msg(response)
    except ConnectionRefusedError:
        logger.error("❌ 无法连接到intelligenced。请确保服务 (intelligenced.py) 正在运行。")
    except Exception as e:
        logger.error(f"❌ 错误: {e}")
    finally:
        if 'sock' in locals():
            sock.close()


def is_oi_runtime_running():
    """检查oi-runtime服务是否正在运行"""
    try:
        # 使用systemctl检查服务状态
        result = subprocess.run(
            ["systemctl", "is-active", "oi-runtime"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )

        # 服务活跃状态为"active"
        return result.stdout.strip() == "active"
    except Exception as e:
        console.print(f"[bold red]检查oi-runtime服务时出错: {str(e)}[/]")
        return False


@click.command()
@click.argument("server_name")
@click.option("--http", is_flag=True, help="Run server over HTTP instead of stdio")
@click.option("--sse", is_flag=True, help="Run server over SSE instead of stdio")
@click.option("--port", type=int, default=1126, help=f"Port for HTTP / SSE mode (default: {1126})")
@click.option("--host", type=str, default="127.0.0.1", help="Host address for HTTP / SSE mode (default: 127.0.0.1)")
@click.help_option("-h", "--help")
def start(server_name, http, sse, port, host):
    msg = {
        "command": "start",
        "server_name": server_name,
        "http": http,
        "sse": sse,
        "port": port,
        "host": host}
    return send_command(msg)


@click.command()
@click.argument("server_name")
@click.help_option("-h", "--help")
def stop(server_name):
    msg = {
        "command": "stop",
        "server_name": server_name,
    }
    return send_command(msg)


@click.command()
@click.argument("server_name")
@click.option("--force", is_flag=True, help="Force reinstall if server is already installed")
@click.help_option("-h", "--help")
def install(server_name, force=False):
    mcp_server_manager = McpServerManager()
    server_metadata = mcp_server_manager.get_mcp_metadata(server_name)
    real_name = mcp_server_manager.get_mcp_server_name(server_name)
    if not server_metadata or real_name:
        console.print(f"[yellow]未找到 名称： {server_name} 的mcp服务[/]")
        return
    description = server_metadata.get("description", "No description available")
    console.print(f"\nMCP Server Name: [bold cyan]{server_name}")
    console.print(f"Description: [dim]{description}\n[/]")

    if not force and not Confirm.ask("Install this server?"):
        console.print("[yellow]Operation cancelled.[/]")
        return
    console.print("[yellow]\nInstalling server...[/]")
    msg = {
        "command": "install",
        "server_name": server_name}

    return send_command(msg)


@click.command()
@click.argument("server_name")
@click.option("--force", is_flag=True, help="Force uninstall if server is installed")
@click.help_option("-h", "--help")
def uninstall(server_name, force=False):
    mcp_server_manager = McpServerManager()

    if mcp_server_manager.server_exists(server_name):
        if not force and not Confirm.ask(f"Uninstall {server_name} server?"):
            console.print("[yellow]Operation cancelled.[/]")
            return
        console.print("[yellow]\nUninstalling server...[/]")
        msg = {
            "command": "uninstall",
            "server_name": server_name}

        return send_command(msg)
    else:
        console.print("[yellow]Server not installed.[/]")


@click.command()
@click.option("--verbose", "-v", is_flag=True, help="Show detailed server configuration")
@click.help_option("-h", "--help")
def list(verbose: bool = False):
    msg = {
        "command": "list_cmd",
        "verbose": verbose
    }
    return send_command(msg)


@click.command()
@click.argument("server_name")
@click.help_option("-h", "--help")
def info(server_name):
    msg = {
        "command": "info",
        "server_name": server_name,
    }
    return send_command(msg)


@click.command()
@click.argument("server_name")
@click.help_option("-h", "--help")
def status(server_name):
    msg = {
        "command": "status",
        "server_name": server_name,
    }
    return send_command(msg)


@click.command()
@click.argument("server_name")
@click.option("--excel", is_flag=True, help="complicate method to show mcp servers message")
@click.help_option("-h", "--help")
def search(server_name, excel=False):
    msg = {
        "command": "search",
        "server_name": server_name,
        "excel": excel
    }
    return send_command(msg)


def handle_exceptions(func):
    """Decorator to catch unhandled exceptions and provide a helpful error message."""

    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception:
            import traceback
            logger.error(f"{traceback.format_exc()}")
            console.print(Traceback(show_locals=True))
            console.print("[bold red]An unexpected error occurred.[/bold red]")
            console.print(
                "Please report this issue on our GitHub repository: "
                "[link=https://github.com/pathintegral-institute/mcpm.sh/issues]https://github.com/pathintegral-institute/mcpm.sh/issues[/link]"
            )

    return wrapper


@click.command()
@click.argument("option", help="操作类型: create/delete/search/list")
@click.option("--name", type=str, help="agent名称")
@click.option("--mcp_list", type=str, help="mcp服务器名称列表，多个用逗号分隔")
@click.help_option("-h", "--help")
def agent(option, name, mcp_list):
    if not is_oi_runtime_running():
        console.print("[bold red]错误: oi-runtime服务未运行，请先启动该服务[/]")
        console.print("[blue]启动命令: sudo systemctl start oi-runtime[/]")
        console.print(
            "[blue]安装参考: https://gitee.com/openeuler/euler-copilot-shell/blob/dev/docs/部署 & 使用手册.md[/]")
        return
    valid_options = ['create', 'delete', 'search', 'list']
    if option not in valid_options:
        console.print(f"错误: 无效的操作类型 '{option}'，必须是以下之一: {', '.join(valid_options)}")
        return

    # 验证必要参数
    if option != 'list':
        if not name:
            console.print("错误: 必须提供agent名称(--name)")
            return
    # 如果是创建操作，需要额外验证mcp_list
    if option == 'create':
        if not mcp_list:
            console.print("错误: 创建操作必须提供mcp服务器列表(--mcp_list)")
            return
        # 可以在这里对mcp_list进行进一步处理，比如分割成列表
        msg = {
            "command": f"{option}_agent",
            "server_names": mcp_list,
            "agent_name": name
        }
    elif option == 'list':
        # list操作不需要agent_name
        msg = {
            "command": f"{option}_agent"
        }
    else:
        # delete和search操作不需要mcp_list
        msg = {
            "command": f"{option}_agent",
            "agent_name": name
        }

    return send_command(msg)


@click.group(
    name="sysintd",
    context_settings=CONTEXT_SETTINGS,
    invoke_without_command=True,
    help="""
        Centralized MCP server management - search, install, run, and  servers.
        
        Manage servers globally, monitor usage, and integrate 
        with openeuler intelligence.
        """,
)
@click.option("-v", "--version", is_flag=True, help="Show version and exit.")
@click.option("-h", "--help", "help_flag", is_flag=True, help="Show this message and exit.")
@click.pass_context
@handle_exceptions
def main(ctx, version, help_flag):
    if version:
        console.print(__version__)
        return

    if help_flag:
        # Show custom help with header and footer for main command only
        # Temporarily disable global footer to avoid duplication
        original_footer = click.rich_click.FOOTER_TEXT
        click.rich_click.FOOTER_TEXT = None
        click.echo(ctx.get_help())
        click.rich_click.FOOTER_TEXT = original_footer
        return

    # If no command was invoked, show help with header and footer
    if ctx.invoked_subcommand is None:
        # Temporarily disable global footer to avoid duplication
        original_footer = click.rich_click.FOOTER_TEXT
        click.rich_click.FOOTER_TEXT = None
        click.echo(ctx.get_help())
        click.rich_click.FOOTER_TEXT = original_footer


main.add_command(search)
main.add_command(list, name="ls")
main.add_command(install)
main.add_command(uninstall)
main.add_command(info)
main.add_command(start)
main.add_command(status)
main.add_command(stop)
main.add_command(agent)

if __name__ == "__main__":
    main()
